package org.ne.springboot.utils.PaperHandleUtils.ReferenceCheckUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;


import org.ne.springboot.utils.PaperHandleUtils.PaperContentCheckUtils.SparkClient;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;



@Slf4j
public class ReferenceCheckUtils {

    // 正则表达式：提取参考文献条目编号，如 [1] 或 1.
    private static final Pattern REF_ENTRY_PATTERN = Pattern.compile("^(\\d+\\.|\\[\\d+])\\s*(.*)$");
    // 正则表达式：提取正文引用，如 [1]、[2-4]、[5,6]
    private static final Pattern CITATION_PATTERN = Pattern.compile("\\[(\\d+(?:-\\d+)?(?:,\\d+(?:-\\d+)?)*)]");

    private static final Pattern REF_TITLE_PATTERN = Pattern.compile("^参\\s*考\\s*文\\s*献$");
    private static final Pattern THANKS_TITLE_PATTERN = Pattern.compile("^致[\\s　]*谢$");


    public static XWPFDocument check(MultipartFile file, String model) throws IOException {
        log.debug("开始参考文献检查, 文件名={}", file == null ? "null" : file.getOriginalFilename());

        //提取参考文献列表和正文带引用的段落
        Map<Integer, String> contentLines = new HashMap<>();
        Map<Integer, String> refLines = new HashMap<>();
        try (InputStream inputStream = file.getInputStream();
             XWPFDocument document = new XWPFDocument(inputStream)) {

            boolean inReferences = false;
            int refIndex = 1;

            for (XWPFParagraph paragraph : document.getParagraphs()) {
                String text = paragraph.getText().trim();
                if (text.isEmpty()) {
                    continue;
                }
                if (THANKS_TITLE_PATTERN.matcher(text).matches()) {
                    break;
                }
                //找到参考文献
                if (REF_TITLE_PATTERN.matcher(text).matches()) {
                    inReferences = true;
                    continue;
                }
                //参考文献部分
                if (inReferences) {
                    //检测手动编号
                    Matcher matcher = REF_ENTRY_PATTERN.matcher(text);
                    if (matcher.matches()) {
                        String content = matcher.group(2);
                        refLines.put(refIndex, content);
                        refIndex++;
                    }
                    //检测自动编号
                    if (paragraph.getNumID() != null) {
                        refLines.put(refIndex, text);
                        refIndex++;
                    }
                }else {
                    //正文引用部分
                    Matcher citationMatcher = CITATION_PATTERN.matcher(text);
                    while (citationMatcher.find()) {
                        String citationGroup = citationMatcher.group(1);
                        String[] parts = citationGroup.split(",");
                        for (String part : parts) {
                            part = part.trim();
                            try {
                                if (part.contains("-")) {
                                    String[] range = part.split("-");
                                    int start = Integer.parseInt(range[0].trim());
                                    int end = Integer.parseInt(range[1].trim());
                                    if (start > end) {
                                        continue;
                                    }
                                    for (int i = start; i <= end; i++) {
                                        contentLines.putIfAbsent(i, text);
                                    }
                                } else {
                                    int index = Integer.parseInt(part.trim());
                                    contentLines.putIfAbsent(index, text);
                                }
                            } catch (NumberFormatException e) {
                                System.out.println(e.getMessage());
                            }
                        }
                    }

                }

            }
        }catch (Exception e) {
            e.printStackTrace();
        }

        //调用AI检查引用内容

        SparkClient sparkClient = new SparkClient();
        //设置模型，controller传参model
        sparkClient.setModel(model);



        /**
         *  "请以严格的JSON格式返回结果，包含以下字段：\n" +
         *             "- correct_citations: 正确引用的数量（整数，表示引用标记存在、格式正确、内容相关的引用数量）\n" +
         *             "- missing_references: 缺失的参考文献编号列表（数组，包含所有在参考文献列表中无对应条目的引用标记序号）\n" +
         *             "- format_errors: 格式错误的引用编号列表（数组，包含所有格式错误的引用标记序号，如无效格式）\n" +
         *             "- content_mismatches: 内容完全不相关的引用编号列表（数组，包含所有段落文本与参考文献内容无任何关联的引用标记序号）\n" +
         *             "- unused_references: 未被引用的参考文献编号列表（数组，包含参考文献列表中有但未被任何引用标记引用的条目序号）\n" +
         *             "- issues: 问题列表（数组，每个元素是一个对象，包含以下字段：\n" +
         *             "  - type: 问题类型（字符串，如\"格式错误\"、\"内容不匹配\"、\"缺失引用\"、\"未引用文献\"）\n" +
         *             "  - description: 详细的中文问题描述（字符串，例如：\"引用标记[5]格式错误，缺少方括号\"）\n" +
         *             "\n" +
         *             "{{format}}" +
         *
         * */
        HashMap<String, Object> format = new HashMap<>();
        format.put("correct_citations","正确引用的数量（整数，表示引用标记存在、格式正确、内容相关的引用数量）");
        format.put("missing_references","缺失的参考文献编号列表（数组，包含所有在参考文献列表中无对应条目的引用标记序号）");
        format.put("format_errors","格式错误的引用编号列表（数组，包含所有格式错误的引用标记序号，如无效格式）");
        format.put("content_mismatches","内容完全不相关的引用编号列表（数组，包含所有段落文本与参考文献内容无任何关联的引用标记序号）");
        format.put("unused_references", "未被引用的参考文献编号列表（数组，包含参考文献列表中有但未被任何引用标记引用的条目序号）");
        format.put("issues", " 问题列表（数组，每个元素是一个对象，包含以下字段：\\n\" +\n" +
                "            \"  - type: 问题类型（字符串，如\\\"格式错误\\\"、\\\"内容不匹配\\\"、\\\"缺失引用\\\"、\\\"未引用文献\\\"）\\n\" +\n" +
                "            \"  - description: 详细的中文问题描述（字符串，例如：\\\"引用标记[5]格式错误，缺少方括号\\\"）\\n\" +");
        sparkClient.setFormat(format);

        // 格式化输入内容（便于 AI 解析）
        StringBuilder citationFormatted = new StringBuilder("引用标记及上下文文本:\n");
        contentLines.forEach((index, text) -> {
            citationFormatted.append(String.format("[%d]: %s\n", index, text));
        });
        StringBuilder refFormatted = new StringBuilder("对应的参考文献列表:\n");
        refLines.forEach((index, content) -> {
            refFormatted.append(String.format("[%d]: %s\n", index, content));
        });

        String content = citationFormatted.toString() + "\n" + refFormatted.toString();
//        System.out.println(content);
        log.debug("size1={}, size2={}", contentLines.size(), refLines.size());
//        log.debug("c1:{}", citationFormatted.toString());
//        log.debug("r1:{}", refFormatted.toString());
        sparkClient.setPrompt("reference");
        Map<String, Object> result = sparkClient.processRequest(citationFormatted.toString(), refFormatted.toString());

        if(!"success".equals(result.get("status"))){
            log.debug("文献引用检查 {}", result);
            throw new IOException("文档引用检查失败: " + result.get("msg"));
        }

        return output((JSONObject) result.get("answer"));

    }

    public static XWPFDocument output(JSONObject reportJson) throws IOException {
        XWPFDocument doc = new XWPFDocument();
//        log.debug("json格式信息:{}" ,reportJson);
//        log.debug("issues={}, {}", reportJson.get("issues"), reportJson.getJSONArray("issues"));
//        JSONObject issues = (JSONObject) reportJson.get("issues");

        try {

            // 1. 添加标题
            addTitle(doc);

            // 2. 添加摘要信息
            addSummarySection(doc, reportJson);

            // 3. 添加详细问题列表
            addIssuesTable(doc, reportJson.getJSONArray("issues"));

            // 4. 添加未引用文献列表
            addUnusedReferences(doc, reportJson.getJSONArray("unused_references"));

        }catch (Exception e) {
            doc.close();
            throw new IOException("生成报告时出错: " + e.getMessage(), e);
        }
        return doc;
    }


    private static void addTitle(XWPFDocument doc) {
        XWPFParagraph titlePara = doc.createParagraph();
        titlePara.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun titleRun = titlePara.createRun();
        titleRun.setText("参考文献检查报告");
        titleRun.setBold(true);
        titleRun.setFontSize(16);
        doc.createParagraph();  // 空行
    }

    private static void addSummarySection(XWPFDocument doc, JSONObject report) {
        XWPFParagraph para = doc.createParagraph();
        XWPFRun run = para.createRun();
        run.setText("报告摘要");
        run.setBold(true);
        run.setFontSize(14);

        para = doc.createParagraph();
        run = para.createRun();
        run.setText("✓ 正确引用数量: " + report.getIntValue("correct_citations"));
        run.addBreak();
        run.setText("✗ 未引用文献数量: " + report.getJSONArray("unused_references").size());
        run.addBreak();
        run.setText("⚠️ 总问题数: " + report.getJSONArray("issues").size());
        doc.createParagraph();  // 空行
    }

    private static void addIssuesTable(XWPFDocument doc, JSONArray issues) {
        if (issues == null || issues.isEmpty()) return;

        XWPFParagraph para = doc.createParagraph();
        XWPFRun run = para.createRun();
        run.setText("详细问题列表");
        run.setBold(true);
        run.setFontSize(14);

        // 创建表格
        XWPFTable table = doc.createTable();
        // 表头
        XWPFTableRow headerRow = table.getRow(0);
        addTableCell(headerRow, 0, "问题类型").setBold(true);
        addTableCell(headerRow, 1, "问题描述").setBold(true);

        // 填充数据
        for (int i = 0; i < issues.size(); i++) {
            JSONObject issue = issues.getJSONObject(i);
            XWPFTableRow row = table.createRow();
            addTableCell(row, 0, issue.getString("type"));
            addTableCell(row, 1, issue.getString("description"));
        }
        doc.createParagraph();  // 空行
    }

    private static void addUnusedReferences(XWPFDocument doc, JSONArray unusedRefs) {
        if (unusedRefs == null || unusedRefs.isEmpty()) return;

        XWPFParagraph para = doc.createParagraph();
        XWPFRun run = para.createRun();
        run.setText("未引用文献列表");
        run.setBold(true);
        run.setFontSize(14);

        para = doc.createParagraph();
        run = para.createRun();
        run.setText("以下参考文献未被正文引用: ");

        // 添加编号列表
        for (int i = 0; i < unusedRefs.size(); i++) {
            XWPFParagraph listPara = doc.createParagraph();
            listPara.setNumID(BigInteger.valueOf(1));  // 使用默认编号样式
            XWPFRun listRun = listPara.createRun();
            listRun.setText("参考文献[" + unusedRefs.getInteger(i) + "]");
        }
    }

    private static XWPFRun addTableCell(XWPFTableRow row, int col, String text) {
        XWPFTableCell cell = col < row.getTableCells().size() ?
                row.getCell(col) : row.addNewTableCell();
        cell.removeParagraph(0);
        XWPFParagraph para = cell.addParagraph();
        XWPFRun run = para.createRun();
        run.setText(text);
        return run;
    }


}
